package cn.mw.cmdb.service.impl;

import cn.mw.cmdb.entity.InstanceInfo;
import cn.mw.cmdb.entity.InstanceInfoExtend;
import cn.mw.cmdb.entity.ModelType;
import cn.mw.cmdb.entity.graph.ComboParam;
import cn.mw.cmdb.entity.graph.EdgeParam;
import cn.mw.cmdb.entity.graph.InstanceModelMapper;
import cn.mw.cmdb.entity.graph.NodeParam;
import cn.mw.cmdb.entity.instanceToPo.*;
import cn.mw.cmdb.entity.modelRelation.*;
import cn.mw.cmdb.enums.InstanceActionType;
import cn.mw.cmdb.mapper.InstanceRelationMapper;
import cn.mw.cmdb.mapper.InstanceTopoCommonViewMapper;
import cn.mw.cmdb.mapper.InstanceTopoCustomViewMapper;
import cn.mw.cmdb.mapper.ModelAssetMapper;
import cn.mw.cmdb.mongoMapper.InstanceHealthHistoryMapper;
import cn.mw.cmdb.mongoMapper.InstanceViewMapper;
import cn.mw.cmdb.mongoMapper.ModelAlertWeightInfoMapper;
import cn.mw.cmdb.mongoMapper.RelationGroupMapper;
import cn.mw.cmdb.param.InstanceSearchParam;
import cn.mw.cmdb.param.TrendQueryParam;
import cn.mw.cmdb.service.InstanceToPoService;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.util.ModelAssetUtils;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.components.mongodb.entity.SubCondition;
import cn.mw.components.mongodb.tool.CriteriaWrapper;
import cn.mw.microMonitorCommon.api.cmdb.AlertWeightConfigInfo;
import cn.mw.microMonitorCommon.api.cmdb.ModelWeightConfigInfo;
import cn.mw.microMonitorCommon.security.dto.MwUser;
import cn.mw.microMonitorCommon.security.utils.SecurityUtils;
import cn.mw.microMonitorCommon.util.DateUtils;
import cn.mw.microMonitorCommon.util.ListMapObjUtils;
import cn.mw.microMonitorCommon.utils.DatabaseUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.neo4j.driver.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class InstanceToPoServiceImpl implements InstanceToPoService {

    @Autowired
    private InstanceViewMapper instanceViewMapper;

    @Autowired
    private ModelAssetMapper modelAssetMapper;

    @Autowired
    private InstanceTopoCustomViewMapper instanceTopoCustomViewMapper;

    @Autowired
    private InstanceTopoCommonViewMapper instanceTopoCommonViewMapper;

    @Autowired
    private InstanceRelationMapper instanceRelationMapper;

    @Autowired
    private CmdbServiceManage cmdbServiceManage;

    @Autowired
    private RelationGroupMapper relationGroupMapper;

    @Autowired
    private ModelAlertWeightInfoMapper modelAlertWeightInfoMapper;

    @Autowired
    private InstanceHealthHistoryMapper instanceHealthHistoryMapper;

    private static final int DEFAULT_SHOW_LEVEL = 3;

    @Override
    public InstanceViewInfo createInstanceView(InstanceViewInfo param) {
        instanceViewMapper.save(param);
        return param;
    }

    @Override
    public boolean editInstanceView(InstanceViewInfo param) {
        Query query = new Query(Criteria.where(DatabaseUtils.getFieldName(InstanceViewInfo::getId)).is(param.getId()));
        Update update = CMDBTool.genMongoUpdate(param, null, null);
        CMDBTool.updateFirst(instanceViewMapper, query, update);
        return true;
    }

    @Override
    public boolean deleteInstanceView(InstanceViewInfo param) throws Exception {
        // 默认视图不支持删除
        if (Long.parseLong(param.getId()) < 0) {
            return false;
        }
        InstanceViewInfo existsView = instanceViewMapper.findById(param.getId());
        if (existsView != null) {
            // 删除实例拓扑
            String instanceId = existsView.getInstanceId();
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            InstanceInfo instanceInfo = instanceService.selectById(instanceId);
            if (instanceInfo != null) {
                String key = String.format("%s_%s_%s", instanceInfo.getModelId(), instanceId, param.getId());
                instanceTopoCustomViewMapper.deleteById(key);
            }
            instanceViewMapper.remove(new Query(Criteria.where(DatabaseUtils.getFieldName(InstanceViewInfo::getId)).is(param.getId())));
        }
        return true;
    }

    @Override
    public List<InstanceViewInfo> getInstanceView(InstanceViewInfo param) throws Exception {
        String instanceId = param.getInstanceId();
        List<InstanceViewInfo> instanceViewInfoList = instanceViewMapper.find(new Query(Criteria.where(DatabaseUtils.getFieldName(InstanceViewInfo::getInstanceId)).is(instanceId)));
        // 业务模型默认使用自定义视图
        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        InstanceInfoExtend instanceInfoExtend = instanceService.selectAggregateById(instanceId);
        if (StringUtils.equals(instanceInfoExtend.getModelType(), ModelType.BusinessModel.getType())) {
            if (CollectionUtils.isEmpty(instanceViewInfoList)) {
                InstanceViewInfo businessModelDefaultView = new InstanceViewInfo();
                businessModelDefaultView.setInstanceId(instanceId);
                businessModelDefaultView.setViewName(InstanceTopoCommonView.DEFAULT_INSTANCE_VIEW_NAME);
                createInstanceView(businessModelDefaultView);
                instanceViewInfoList.add(0, businessModelDefaultView);
            }
        } else {
            //增加默认视图
            InstanceViewInfo defaultView = new InstanceViewInfo();
            defaultView.setInstanceId(param.getInstanceId());
            defaultView.setId(InstanceTopoCommonView.DEFAULT_INSTANCE_VIEW_ID);
            defaultView.setViewName(InstanceTopoCommonView.DEFAULT_INSTANCE_VIEW_NAME);
            instanceViewInfoList.add(0, defaultView);
        }
        return instanceViewInfoList;
    }

    @Override
    public InstanceTopoView dealInstanceToPo(QueryInstanceRelationToPoParam param) throws Exception {
        InstanceTopoView instanceTopoView = new InstanceTopoView();
        LastData lastData = new LastData();
        //找到根节点,并获取实例拓扑配置信息
        if (StringUtils.isNotEmpty(param.getAction())) {
            //实例拓扑操作
            //新增模型拓扑框
            InstanceActionType actionType = InstanceActionType.valueOf(param.getAction());
            switch (actionType) {
                //初次打开页面,显示实例拓扑
                case init -> {
                    initInstanceTopo(param, instanceTopoView);
                    lastData = instanceTopoView.getData();
                }
                case addModel -> lastData = doAddNewModel(param);
                case removeModel -> lastData = removeModelOrInstance(param, true);
                case removeInstance -> lastData = removeModelOrInstance(param, false);
                case addInstance -> lastData = doAddNewInstance(param);
                case addLine -> lastData = doAddNewLine(param);
            }

            HideModelDataView hideModelDataView = new HideModelDataView();
            hideModelDataView.setHide(param.getHideModelIds());
            hideModelDataView.setShow(param.getShowModelIds());
            instanceTopoView.setHideModelData(hideModelDataView);
            instanceTopoView.setIntanceViewId(param.getInstanceViewId());
            instanceTopoView.setData(lastData);
        }
        return instanceTopoView;
    }

    @Override
    public List<ModelAssociatedView> getModelRelationInfo(QueryInstanceRelationToPoParam param) throws Exception {
        List<ModelAssociatedView> views = new ArrayList<>();
        QueryInstanceRelationsParam qparam = param.getOwmRelationsParam();
        if (qparam == null) {
            return views;
        }
        List<EdgeParam> edgesLastInfo = new ArrayList<>();
        List<ComboParam> combosLastInfo = new ArrayList<>();
        if (param.getData() != null) {
            edgesLastInfo = param.getData().getEdges();
            combosLastInfo = param.getData().getCombos();
        }
        String modelId = qparam.getModelId();
        // 查询模型关系分组
        List<RelationGroupDTO> groupDTOS = relationGroupMapper.find(new Query(CriteriaWrapper.where(ModelRelationGroupDTO::getOwnModelId).is(modelId)));

        //查询所有关系信息,根据模型id获取每个关系对应的名称
        ModelAsset modelAsset = null;
        Optional<ModelAsset> result = modelAssetMapper.findById(param.getOwmRelationsParam().getModelId());
        if (result.isPresent()) {
            modelAsset = result.get();
        }

        for (RelationGroupDTO modelRelationGroupDTO : groupDTOS) {
            //设置本端和对端关系信息,记录对端分组Id
            List<ModelAssociatedView> list = ModelAssociatedView.genViewList(modelAsset, modelRelationGroupDTO.getId());
            if (list.size() > 0) {
                for (ModelAssociatedView modelAssociatedView : list) {
                    modelAssociatedView.setGroupId(modelRelationGroupDTO.getId());
                    modelAssociatedView.setGroupName(modelRelationGroupDTO.getRelationGroupName());
                }
                views.addAll(list);
            }
        }

        //默认所有模型只有一个上级
        List<String> sourceList = new ArrayList<>();
        //由于前端新增实例数据时，获取不了 关联的模型Id和实例id
        //根据参数relationInstanceList中的新增实例的modelId，去lastData的edges中获取source
        for (EdgeParam edge : edgesLastInfo) {
            //循环获取
            String target = edge.getTarget();
            String[] targetStr = target.split("_");
            if (targetStr.length > 1 && targetStr[0].equals(qparam.getModelId() + "")) {
                String source = edge.getSource();
                String lastModelId = source.split("_")[0];
                sourceList.add(lastModelId);
            }
        }
        //对combos数据去重
        List<ComboParam> modelIdDistinctList = combosLastInfo.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(s -> s.getId()))), ArrayList::new));
        List<String> modelIds = new ArrayList<>();
        //获取所有已存在的模型id
        for (ComboParam m : modelIdDistinctList) {
            modelIds.add(m.getId());
        }

        //现阶段，暂定：拓扑实例中，所有的模型只能出现一次，避免出现一个模型有多个上级的情况
        Iterator<ModelAssociatedView> it = views.iterator();
        //去除已出现的模型数据
        while (it.hasNext()) {
            ModelAssociatedView view = it.next();
            if (modelIds.contains(view.getOppositeModelId())) {
                it.remove();
            }
        }

        return views;
    }

    @Override
    public boolean addInstanceToPo(QueryInstanceRelationToPoParam param) {
        Map<String, ComboParam> modelMap = new HashMap<>();
        if (null != param.getData()) {
            LastData topoData = param.getData();

            // 获取topo实例节点
            List<String> instanceNodeIds = topoData.getNodes().stream().map(NodeParam::getId).distinct().toList();

            // 获取连线数据
            List<EdgeParam> edges = topoData.getEdges();

            boolean isDefaultView = StringUtils.equals(param.getInstanceViewId(), InstanceTopoCommonView.DEFAULT_INSTANCE_VIEW_ID);
            List instanceTopoCommonViewList = new ArrayList<>();
            Set<String> existsKeys = new HashSet<>();
            String key;
            for (EdgeParam edgeParam : edges) {
                if (edgeParam.getIsEmptyLine() != null && edgeParam.getIsEmptyLine()) {
                    continue;
                }
                if (instanceNodeIds.contains(edgeParam.getSource()) && instanceNodeIds.contains(edgeParam.getTarget())) {
                    key = String.format("%s_%s", edgeParam.getSource(), edgeParam.getTarget());
                    if (existsKeys.contains(key)) {
                        continue;
                    }
                    existsKeys.add(key);
                    if (isDefaultView) {
                        InstanceTopoCommonView sourceNode = new InstanceTopoCommonView();
                        InstanceTopoCommonView targetNode = new InstanceTopoCommonView();
                        targetNode.setId(edgeParam.getTarget());
                        sourceNode.setId(edgeParam.getSource());
                        InstanceCommonRelation instanceCommonRelation = new InstanceCommonRelation();
                        instanceCommonRelation.setEndNode(targetNode);
                        sourceNode.addOutInstanceRelation(instanceCommonRelation);
                        instanceTopoCommonViewList.add(sourceNode);
                    } else {
                        InstanceTopoCustomView sourceNode = new InstanceTopoCustomView();
                        InstanceTopoCustomView targetNode = new InstanceTopoCustomView();
                        targetNode.setId(edgeParam.getTarget());
                        sourceNode.setId(edgeParam.getSource());
                        InstanceCustomRelation instanceCustomRelation = new InstanceCustomRelation();
                        instanceCustomRelation.setEndNode(targetNode);
                        sourceNode.addOutInstanceRelation(instanceCustomRelation);
                        instanceTopoCommonViewList.add(sourceNode);
                    }
                }
            }

            if (isDefaultView) {
                // 默认视图,所有实例放在一个拓扑图里
                dealWithDefaultView(instanceTopoCommonViewList);
            } else {
                // 处理自定义视图
                dealWithCustomView(instanceTopoCommonViewList, param.getInstanceViewId());
            }
        }
        return true;
    }

    @Override
    public List<IntanceTopoSelView> getInstanceTopoSelTree(QueryInstanceRelationToPoParam param) {
        String ownModelId = param.getOwmRelationsParam().getModelId();
        String ownInstanceId = param.getOwmRelationsParam().getInstanceId();

        NodeParam ownNodeParam = new NodeParam(ownModelId, ownInstanceId);

        //模型映射关系
        Map<String, ComboParam> comboParamMap = new HashMap<>();
        if (null != param.getData().getCombos()) {
            for (ComboParam comboParam : param.getData().getCombos()) {
                comboParamMap.put(comboParam.getId(), comboParam);
            }

        }

        //在当前图形节点中去掉起始节点
        List<NodeParam> nodeParamList = param.getData().getNodes();
        Map<String, NodeParam> nodeParamMap = new HashMap<>();
        if (null != nodeParamList) {
            for (NodeParam nodeParam : nodeParamList) {
                nodeParamMap.put(nodeParam.getId(), nodeParam);
            }
        }
        nodeParamList.remove(ownNodeParam);

        //遍历所有节点构造连线
        //过滤已经存在的连线
        List<EdgeParam> existEdges = param.getData().getEdges();
        List<EdgeParam> newEdgeParamList = new ArrayList<>();
        for (NodeParam endNodeParam : nodeParamList) {
            EdgeParam edgeParam = new EdgeParam(ownNodeParam, endNodeParam);
            if (!existEdges.contains(edgeParam)) {
                newEdgeParamList.add(edgeParam);
            }
        }

        //根据能够选择的连线构造显示的数据格式
        Map<String, List<EdgeParam>> listMap = new HashMap<>();
        for (EdgeParam edgeParam : newEdgeParamList) {
            List<EdgeParam> list = listMap.get(edgeParam.getSource());
            if (null == list) {
                list = new ArrayList<>();
                listMap.put(edgeParam.getSource(), list);
            }
            list.add(edgeParam);
        }

        List<IntanceTopoSelView> ret = new ArrayList<>();

        //把可以连接的边,分解成模型和实例
        List<EdgeParam> modelList = listMap.get(ownNodeParam.getId());
        if (null != modelList) {
            for (EdgeParam edgeParam : modelList) {
                NodeParam nodeParam = nodeParamMap.get(edgeParam.getTarget());
                if (null != nodeParam) {
                    IntanceTopoSelView intanceTopoSelView = new IntanceTopoSelView();
                    ComboParam comboParam = comboParamMap.get(nodeParam.getCombo());
                    intanceTopoSelView.extractFrom(comboParam);

                    IntanceTopoSelView modelView = null;
                    for (IntanceTopoSelView view : ret) {
                        if (view.getId().equals(intanceTopoSelView.getId())) {
                            modelView = view;
                            break;
                        }
                    }

                    if (null == modelView) {
                        ret.add(intanceTopoSelView);
                    } else {
                        intanceTopoSelView = modelView;
                    }

                    intanceTopoSelView.extractChild(nodeParam);
                }
            }
        }
        return ret;
    }

    @Override
    public ModelAlertWeightInfo addOrUpdateModelAlertWeightInfo(ModelAlertWeightInfo modelAlertWeightInfo) throws Exception {
        ModelAlertWeightInfo existsInfo = modelAlertWeightInfoMapper.findOne(new Query(
                CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getInstanceId)).is(modelAlertWeightInfo.getInstanceId())
                        .andOperator(CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getInstanceViewId)).is(modelAlertWeightInfo.getInstanceViewId())
                                , CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getOwnModelId)).is(modelAlertWeightInfo.getOwnModelId()))));
        MwUser mwUser = SecurityUtils.getUser();
        if (existsInfo != null) {
            modelAlertWeightInfo.setId(existsInfo.getId());
            modelAlertWeightInfo.setModifier(mwUser.getId());
            modelAlertWeightInfo.setModificationTime(new Date());
        } else {
            modelAlertWeightInfo.setCreater(mwUser.getId());
            modelAlertWeightInfo.setCreateTime(new Date());
        }
        modelAlertWeightInfoMapper.save(modelAlertWeightInfo);
        return modelAlertWeightInfo;
    }

    @Override
    public ModelAlertWeightInfo getModelAlertWeightInfo(ModelAlertWeightInfo modelAlertWeightInfo) throws Exception {
        Query query = new Query(
                CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getInstanceId)).is(modelAlertWeightInfo.getInstanceId())
                        .andOperator(CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getInstanceViewId)).is(modelAlertWeightInfo.getInstanceViewId())
                                , CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getOwnModelId)).is(modelAlertWeightInfo.getOwnModelId())));
        return modelAlertWeightInfoMapper.findOne(query);
    }

    @Override
    public boolean deleteModelAlertWeightInfo(ModelAlertWeightInfo modelAlertWeightInfo) throws Exception {
        Query query = new Query(
                CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getInstanceId)).is(modelAlertWeightInfo.getInstanceId())
                        .andOperator(CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getInstanceViewId)).is(modelAlertWeightInfo.getInstanceViewId())
                                , CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getOwnModelId)).is(modelAlertWeightInfo.getOwnModelId())));
        modelAlertWeightInfoMapper.remove(query);
        return true;
    }

    @Override
    public List<AlertWeightConfigInfo> getAlertWeightConfigInfosByInstanceId(String instanceId) throws Exception {
        List<AlertWeightConfigInfo> alertWeightConfigInfoList = new ArrayList<>();
        // 查询所有的业务实例
        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        InstanceSearchParam instanceSearchParam = new InstanceSearchParam();
        instanceSearchParam.addSubCondition(CMDBTool.getFieldName(InstanceInfoExtend::getModelType), new SubCondition(CriteriaOpsType.is.name(), ModelType.BusinessModel.getType()));
        List<InstanceInfoExtend> businessInstances = instanceService.aggregateList(instanceSearchParam);

        // 通过实例id查询相关的业务实例
        if (CollectionUtils.isNotEmpty(businessInstances)) {
            List<String> businessInstanceIdList = businessInstances.stream().map(InstanceInfoExtend::getId).toList();
            Map<String, InstanceInfoExtend> instanceId2InfoMap = businessInstances.stream().collect(Collectors.toMap(InstanceInfoExtend::getId, item -> item, (o1, o2) -> o2));

            List<InstanceTopoCustomView> instanceTopoCustomViews = instanceTopoCustomViewMapper.findByInstanceIdIn(businessInstanceIdList);
            if (CollectionUtils.isNotEmpty(instanceTopoCustomViews)) {
                Iterator<InstanceTopoCustomView> iterator = instanceTopoCustomViews.iterator();
                // 过滤出包换指定实例的业务
                InstanceTopoCustomView instanceTopoCustomView;
                List<String> relationInstanceIds;
                while (iterator.hasNext()) {
                    relationInstanceIds = new ArrayList<>();
                    instanceTopoCustomView = iterator.next();
                    getRelationInstanceIds(instanceTopoCustomView, relationInstanceIds);
                    if (!relationInstanceIds.contains(instanceId)) {
                        iterator.remove();
                    }
                }
            }
            // 通过业务实例拼接参数
            if (CollectionUtils.isNotEmpty(instanceTopoCustomViews)) {
                businessInstanceIdList = instanceTopoCustomViews.stream().map(InstanceTopoCustomView::getInstanceId).toList();
                List<ModelAlertWeightInfo> modelAlertWeightInfoList = modelAlertWeightInfoMapper.find(new Query(CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getInstanceId)).in(businessInstanceIdList)));
                if (CollectionUtils.isNotEmpty(modelAlertWeightInfoList)) {
                    Map<String, List<ModelAlertWeightInfo>> key2ModelAlertWeightInfoListMap = modelAlertWeightInfoList.stream().collect(Collectors.groupingBy(item -> String.format("%s_%s", item.getInstanceId(), item.getInstanceViewId())));
                    AlertWeightConfigInfo alertWeightConfigInfo;
                    String key;
                    for (InstanceTopoCustomView instanceTopoCustomView : instanceTopoCustomViews) {
                        key = String.format("%s_%s", instanceTopoCustomView.getInstanceId(), instanceTopoCustomView.getInstanceViewId());
                        if (key2ModelAlertWeightInfoListMap.containsKey(key)) {
                            alertWeightConfigInfo = new AlertWeightConfigInfo();
                            alertWeightConfigInfo.setInstanceId(instanceTopoCustomView.getInstanceId());
                            alertWeightConfigInfo.setInstanceName(instanceId2InfoMap.get(instanceTopoCustomView.getInstanceId()).getInstanceName());
                            alertWeightConfigInfo.setInstanceViewId(instanceTopoCustomView.getInstanceViewId());
                            alertWeightConfigInfo.setModelWeightConfigInfoList(parseModelWeightConfigInfo(instanceTopoCustomView, key2ModelAlertWeightInfoListMap.get(key)));
                            alertWeightConfigInfoList.add(alertWeightConfigInfo);
                        }
                    }
                }
            }
        }

        // 根据业务实例查询模型权重配置
        return alertWeightConfigInfoList;
    }

    @Override
    public List<String> getRelationInstanceIds(String modelId, String instanceId) throws Exception {
        List<String> instanceIds = new ArrayList<>();
        List<InstanceViewInfo> instanceViewInfoList = instanceViewMapper.find(new Query(Criteria.where(DatabaseUtils.getFieldName(InstanceViewInfo::getInstanceId)).is(instanceId)));
        // 获取默认视图
        if (CollectionUtils.isNotEmpty(instanceViewInfoList)) {
            String instanceViewId = null;
            if (instanceViewInfoList.size() == 1) {
                instanceViewId = instanceViewInfoList.get(0).getId();
            } else {
                for (InstanceViewInfo instanceViewInfo : instanceViewInfoList) {
                    if (instanceViewInfo.getViewName().equals(InstanceTopoCommonView.DEFAULT_INSTANCE_VIEW_NAME)) {
                        instanceViewId = instanceViewInfo.getId();
                    }
                }
            }
            if (instanceViewId != null) {
                // 自定义视图
                String key = String.format("%s_%s_%s", modelId, instanceId, instanceViewId);
                Optional<InstanceTopoCustomView> result = instanceTopoCustomViewMapper.findById(key);
                InstanceTopoCustomView instanceTopoCustomView = null;
                if (result.isPresent()) {
                    instanceTopoCustomView = result.get();
                    analysisCustomInstanceToPo(instanceTopoCustomView, instanceIds, new ArrayList<>(), instanceViewId);
                }
            }
        }
        return instanceIds.stream().filter(item -> !instanceId.equals(item)).toList();
    }

    @Override
    public InstanceHealthTrendVo getBusinessHealthTrend(String instanceId, TrendQueryParam queryParam) throws Exception {
        List<InstanceHealthHistoryDTO> dataList = instanceHealthHistoryMapper.find(new Query(CriteriaWrapper.where(CMDBTool.getFieldName(InstanceHealthHistoryDTO::getInstanceId)).is(instanceId)));
        dataList.sort(((o1, o2) -> o2.getUpdateTime().compareTo(o1.getUpdateTime())));
        return getTrendByDay(dataList);
    }

    private InstanceHealthTrendVo getTrendByDay(List<InstanceHealthHistoryDTO> dataList) {
        InstanceHealthTrendVo result = new InstanceHealthTrendVo();
        Calendar calendar = Calendar.getInstance();
        Date endTime = calendar.getTime();
        calendar.add(Calendar.HOUR, -12);
        Date startTime = calendar.getTime();

        Double lastValue = 100.0;
        calendar.setTime(startTime);
        String dateFormat = "yyyy-MM-dd HH:mm";
        List<String> xdata = new ArrayList<>();
        List<Double> ydata = new ArrayList<>();
        while (!calendar.getTime().after(endTime)) {
            String currentTime = DateUtils.format(calendar.getTime(), dateFormat);
            Optional<InstanceHealthHistoryDTO> currentData = dataList.stream().filter(dp -> DateUtils.format(dp.getUpdateTime(), dateFormat).equals(currentTime)).findFirst();
            if (currentData.isPresent()) {
                // 如果存在对应的时间点数据 使用它
                lastValue = currentData.get().getHealthCount();
                xdata.add(currentTime);
                ydata.add(lastValue);
            } else {
                // 如果不存在 使用上一个时间节点的值补齐
                xdata.add(currentTime);
                ydata.add(lastValue);
            }
            // 时间增加1分钟
            calendar.add(Calendar.MINUTE, 1);
        }
        result.setXdata(xdata);
        result.setYdata(ydata);
        return result;
    }

    @Override
    public boolean updateInstanceHealth(String instanceId, Double healthCount) {
        InstanceHealthHistoryDTO instanceHealthHistoryDTO = new InstanceHealthHistoryDTO();
        instanceHealthHistoryDTO.setInstanceId(instanceId);
        instanceHealthHistoryDTO.setHealthCount(healthCount);
        instanceHealthHistoryDTO.setUpdateTime(new Date());
        instanceHealthHistoryMapper.save(instanceHealthHistoryDTO);
        return true;
    }

    private List<ModelWeightConfigInfo> parseModelWeightConfigInfo(InstanceTopoCustomView instanceTopoCustomView, List<ModelAlertWeightInfo> modelAlertWeightInfoList) {
        List<ModelWeightConfigInfo> modelWeightConfigInfoList = new ArrayList<>();
        Map<String, List<String>> modelId2InstanceListMap = new HashMap<>();
        getRelationModelId2InstanceIds(instanceTopoCustomView, modelId2InstanceListMap);
        ModelWeightConfigInfo modelWeightConfigInfo;
        for (ModelAlertWeightInfo modelAlertWeightInfo : modelAlertWeightInfoList) {
            modelWeightConfigInfo = new ModelWeightConfigInfo();
            modelWeightConfigInfo.setWeight(modelAlertWeightInfo.getWeight());
            modelWeightConfigInfo.setModelId(modelAlertWeightInfo.getOwnModelId());
            modelWeightConfigInfo.setAlertLevelList(modelAlertWeightInfo.getAlertLevelList());
            modelWeightConfigInfo.setInstanceIds(modelId2InstanceListMap.get(modelAlertWeightInfo.getOwnModelId()));
            modelWeightConfigInfoList.add(modelWeightConfigInfo);
        }
        return modelWeightConfigInfoList;
    }

    private void getRelationModelId2InstanceIds(InstanceTopoCustomView instanceTopoCustomView, Map<String, List<String>> modelId2InstanceListMap) {
        if (instanceTopoCustomView != null && instanceTopoCustomView.getInInstanceRelations() != null) {
            for (InstanceCustomRelation instanceCustomRelation : instanceTopoCustomView.getOutInstanceRelations()) {
                if (!modelId2InstanceListMap.containsKey(instanceCustomRelation.getEndNode().getModelId())) {
                    modelId2InstanceListMap.put(instanceCustomRelation.getEndNode().getModelId(), new ArrayList<>());
                }
                modelId2InstanceListMap.get(instanceCustomRelation.getEndNode().getModelId()).add(instanceCustomRelation.getEndNode().getInstanceId());
                getRelationModelId2InstanceIds(instanceCustomRelation.getEndNode(), modelId2InstanceListMap);
            }
        }
    }

    private void getRelationInstanceIds(InstanceTopoCustomView instanceTopoCustomView, List<String> relationIds) {
        if (instanceTopoCustomView != null && instanceTopoCustomView.getInInstanceRelations() != null) {
            for (InstanceCustomRelation instanceCustomRelation : instanceTopoCustomView.getOutInstanceRelations()) {
                relationIds.add(instanceCustomRelation.getEndNode().getInstanceId());
                getRelationInstanceIds(instanceCustomRelation.getEndNode(), relationIds);
            }
        }
    }

    private void dealWithDefaultView(List<InstanceTopoCommonView> instanceTopoCommonViewList) {
        Map<String, List<InstanceTopoCommonView>> id2ViewListMap = instanceTopoCommonViewList.stream().collect(Collectors.groupingBy(InstanceTopoCommonView::getId));
        InstanceTopoCommonView InstanceTopoCommonView;
        for (Map.Entry<String, List<InstanceTopoCommonView>> entry : id2ViewListMap.entrySet()) {
            InstanceTopoCommonView = new InstanceTopoCommonView();
            InstanceTopoCommonView.setId(entry.getKey());
            InstanceTopoCommonView.setModelId(entry.getKey().split("_")[0]);
            InstanceTopoCommonView.setInstanceId(entry.getKey().split("_")[1]);
            InstanceTopoCommonView.setOutInstanceRelations(new ArrayList<>());
            for (InstanceTopoCommonView view : entry.getValue()) {
                InstanceTopoCommonView.getOutInstanceRelations().addAll(view.getOutInstanceRelations());
            }
            // 先清除实例关联关系 然后再创建关系
            instanceRelationMapper.deleteInstanceRelationByInstanceId(entry.getKey());
            instanceTopoCommonViewMapper.save(InstanceTopoCommonView);
        }
    }

    private void dealWithCustomView(List<InstanceTopoCustomView> instanceTopoCommonViewList, String instanceViewId) {
        instanceTopoCustomViewMapper.deleteByInstanceViewId(instanceViewId);
        Map<String, List<InstanceTopoCustomView>> id2ViewListMap = instanceTopoCommonViewList.stream().collect(Collectors.groupingBy(InstanceTopoCustomView::getId));
        InstanceTopoCustomView instanceTopoCustomView;
        for (Map.Entry<String, List<InstanceTopoCustomView>> entry : id2ViewListMap.entrySet()) {
            instanceTopoCustomView = new InstanceTopoCustomView();
            instanceTopoCustomView.setId(String.format("%s_%s", entry.getKey(), instanceViewId));
            instanceTopoCustomView.setModelId(entry.getKey().split("_")[0]);
            instanceTopoCustomView.setInstanceId(entry.getKey().split("_")[1]);
            instanceTopoCustomView.setOutInstanceRelations(new ArrayList<>());
            for (InstanceTopoCustomView view : entry.getValue()) {
                view.getOutInstanceRelations().forEach(item -> {
                    if (item.getEndNode() != null) {
                        item.getEndNode().setId(String.format("%s_%s", item.getEndNode().getId(), instanceViewId));
                    }
                });
                instanceTopoCustomView.getOutInstanceRelations().addAll(view.getOutInstanceRelations());
            }
            instanceTopoCustomViewMapper.save(instanceTopoCustomView);
        }
    }

    private LastData doAddNewInstance(QueryInstanceRelationToPoParam param) throws Exception {
        QueryInstanceRelationsParam qparam = param.getOppoRelationsParamList().get(0);
        LastData lastData = param.getData();
        List<NodeParam> nodeParams = lastData.getNodes();

        List<String> instanceIds = qparam.getInstanceIds();
        List<String> allInstanceIds = new ArrayList<>();
        allInstanceIds.addAll(instanceIds);

        //获取实例信息
        Map<String, InstanceModelMapper> instanceModelMap = doGetInstanceModelMap(allInstanceIds);

        for (String instanceId : qparam.getInstanceIds()) {
            NodeParam nodeParam = new NodeParam();
            nodeParam.setRealId(instanceId);
            nodeParam.extractInfoFrom(instanceModelMap);
            NodePosInfo pos = findAddInstancePos(nodeParam, lastData);
            nodeParams.add(pos.getPos(), nodeParam);
            nodeParam.setLevel(pos.getLevel());
        }

        //删除nodes中的“无实例”实例数据
        Iterator<NodeParam> it = lastData.getNodes().iterator();
        while (it.hasNext()) {
            NodeParam m = it.next();
            if (qparam.getModelId().equals(m.getCombo())
                    && NodeParam.EMPTY_LABEL.equals(m.getLabel())) {
                it.remove();
                break;
            }
        }

        return lastData;
    }

    private NodePosInfo findAddInstancePos(NodeParam nodeParam, LastData data) {
        NodePosInfo nodePosInfo = new NodePosInfo();
        //找到相同combo的节点
        int startIndex = -1;
        int level = 0;
        int lastNodePos = data.getNodes().size() - 1;
        for (int i = 0; i < data.getNodes().size(); i++) {
            NodeParam node = data.getNodes().get(i);
            if (node.getCombo().equals(nodeParam.getCombo())) {
                startIndex = i;
                level = node.getLevel();
            }

            if (startIndex > 0) {
                if (!node.getCombo().equals(nodeParam.getCombo())) {
                    nodePosInfo.setPos(i);
                    nodePosInfo.setLevel(level);
                    break;
                }

                if (i == lastNodePos) {
                    nodePosInfo.setPos(i + 1);
                    nodePosInfo.setLevel(level);
                }
            }
        }

        return nodePosInfo;
    }

    private Map<String, InstanceModelMapper> doGetInstanceModelMap(List<String> allInstanceIds) throws Exception {
        Map<String, InstanceModelMapper> instanceMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(allInstanceIds)) {
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            List<InstanceInfo> instanceInfoList= instanceService.selectListByIds(allInstanceIds);
            for (InstanceInfo instanceInfo : instanceInfoList) {
                InstanceModelMapper instanceModelMapper = InstanceModelMapper.builder()
                        .instanceId(instanceInfo.getId())
                        .instanceName(instanceInfo.getInstanceName())
                        .modelId(instanceInfo.getModelId())
                        .build();
                instanceMap.put(instanceModelMapper.getInstanceId(), instanceModelMapper);
            }
        }
        return instanceMap;
    }

    private LastData doAddNewLine(QueryInstanceRelationToPoParam param) {
        LastData lastData = param.getData();
        QueryInstanceRelationsParam sourceParam = param.getOwmRelationsParam();
        List<List<String>> targetNodes = param.getTargetNodes();

        List<SortNewEdge> sortNewEdges = new ArrayList<>();
        if (null != sourceParam && null != targetNodes) {
            NodeParam start = new NodeParam(sourceParam.getModelId(), sourceParam.getInstanceIds().get(0));
            for (List<String> targetNodeInfo : targetNodes) {
                NodeParam end = new NodeParam(targetNodeInfo.get(0), targetNodeInfo.get(1));
                EdgeParam edgeParam = new EdgeParam(start, end);
                SortNewEdge sortNewEdge = new SortNewEdge(edgeParam);
                sortNewEdges.add(sortNewEdge);
            }

            List<EdgeParam> edgeParams = lastData.getEdges();
            if (null != edgeParams) {
                for (EdgeParam edgeParam : edgeParams) {
                    SortNewEdge sortNewEdge = new SortNewEdge(edgeParam);
                    sortNewEdges.add(sortNewEdge);
                }
            }

            Map<String, SortNode> sortNodeMap = new HashMap<>();
            for (int i = 0; i < lastData.getNodes().size(); i++) {
                NodeParam nodeParam = lastData.getNodes().get(i);
                SortNode sortNode = new SortNode(nodeParam, i);
                sortNodeMap.put(nodeParam.getId(), sortNode);
            }

            for (SortNewEdge sortNewEdge : sortNewEdges) {
                SortNode startSortNode = sortNodeMap.get(sortNewEdge.getEdgeParam().getSource());
                SortNode endSortNode = sortNodeMap.get(sortNewEdge.getEdgeParam().getTarget());
                if (null != startSortNode && null != endSortNode) {
                    sortNewEdge.setStartIndex(startSortNode.getIndex());
                    sortNewEdge.setEndIndex(endSortNode.getIndex());
                }
            }

            Collections.sort(sortNewEdges);
            List<EdgeParam> newEdgeParams = sortNewEdges.stream().map(SortNewEdge::getEdgeParam).collect(Collectors.toList());

            if (newEdgeParams.size() > 0) {
                lastData.setEdges(newEdgeParams);
            }
        }

        return lastData;
    }

    private LastData removeModelOrInstance(QueryInstanceRelationToPoParam param, boolean isDeleteModel) {
        List<NodeParam> nodesInfo = new ArrayList<>();
        List<EdgeParam> edgesInfo = new ArrayList<>();
        List<ComboParam> combosInfo = new ArrayList<>();
        if (param.getOppoRelationsParamList() != null && param.getOppoRelationsParamList().size() > 0) {
            List<NodeParam> nodesLastInfo = new ArrayList<>();
            List<EdgeParam> edgesLastInfo = new ArrayList<>();
            List<ComboParam> combosLastInfo = new ArrayList<>();
            if (param.getData() != null) {
                LastData lastDataAll = param.getData();
                nodesLastInfo = lastDataAll.getNodes();
                edgesLastInfo = lastDataAll.getEdges();
                combosLastInfo = lastDataAll.getCombos();
            }
            //默认所有模型只有一个上级
            for (QueryInstanceRelationsParam qparam : param.getOppoRelationsParamList()) {
                //删除模型
                if (isDeleteModel) {
                    doDelModel(qparam, nodesLastInfo, edgesLastInfo, combosLastInfo);
                } else {
                    //删除实例
                    doDelInstance(qparam, nodesLastInfo, edgesLastInfo, combosLastInfo, nodesInfo, edgesInfo);
                }
            }
            nodesInfo.addAll(nodesLastInfo);
            edgesInfo.addAll(edgesLastInfo);
            combosInfo.addAll(combosLastInfo);
        }
        Comparator<NodeParam> comparatorNode = Comparator.comparing(NodeParam::getLevel).thenComparing(NodeParam::getCombo);
        List<NodeParam> nodesInfos = nodesInfo.stream().sorted(comparatorNode).collect(Collectors.toList());

        LastData lastData = new LastData();
        lastData.setNodes(nodesInfos);

        Comparator<EdgeParam> comparatorEdge = Comparator.comparing(EdgeParam::getSource).thenComparing(EdgeParam::getTarget);
        List<EdgeParam> edgesInfos = edgesInfo.stream().sorted(comparatorEdge).collect(Collectors.toList());
        lastData.setEdges(edgesInfos);
        lastData.setCombos(combosInfo);

        return lastData;
    }

    private void doDelModel(QueryInstanceRelationsParam qparam, List<NodeParam> nodesLastInfo, List<EdgeParam> edgesLastInfo, List<ComboParam> combosLastInfo) {
        Iterator<NodeParam> nodeIts = nodesLastInfo.iterator();
        while (nodeIts.hasNext()) {
            NodeParam s = nodeIts.next();
            if ((qparam.getModelId()).equals(s.getCombo())) {
                nodeIts.remove();
            }
        }
        Iterator<EdgeParam> edgeIts = edgesLastInfo.iterator();
        while (edgeIts.hasNext()) {
            EdgeParam s = edgeIts.next();

            String[] sourceStr = s.getSource().split(EdgeParam.SEP);
            if (sourceStr[0].equals(qparam.getModelId().toString())) {
                edgeIts.remove();
            }

            String[] targetStr = s.getTarget().split(EdgeParam.SEP);
            if (targetStr[0].equals(qparam.getModelId().toString())) {
                edgeIts.remove();
            }
        }
        Iterator<ComboParam> combosIts = combosLastInfo.iterator();
        while (combosIts.hasNext()) {
            ComboParam s = combosIts.next();
            if (s.getId().equals(qparam.getModelId())) {
                combosIts.remove();
            }
        }
    }

    private void doDelInstance(QueryInstanceRelationsParam qparam, List<NodeParam> nodesLastInfo, List<EdgeParam> edgesLastInfo
            , List<ComboParam> combosLastInfo, List<NodeParam> nodesInfo, List<EdgeParam> edgesInfo) {
        for (String instanceId : qparam.getInstanceIds()) {
            Iterator<NodeParam> nodeIts = nodesLastInfo.iterator();
            while (nodeIts.hasNext()) {
                NodeParam s = nodeIts.next();
                if ((qparam.getModelId()).equals(s.getCombo()) && instanceId.equals(s.getRealId())) {
                    nodeIts.remove();
                }
            }

            Iterator<EdgeParam> edgeIts = edgesLastInfo.iterator();

            String delTarget = qparam.getModelId() + EdgeParam.SEP + instanceId;
            List<String> sourceList = new ArrayList<>();
            List<String> targetList = new ArrayList<>();

            //删除与点有关的边
            while (edgeIts.hasNext()) {
                EdgeParam s = edgeIts.next();
                if (delTarget.equals(s.getTarget())) {
                    sourceList.add(s.getSource());
                    edgeIts.remove();

                }

                if (delTarget.equals(s.getSource())) {
                    targetList.add(s.getTarget());
                    edgeIts.remove();
                }
            }

            //实例删除后，判断该模型下是否还有实例，没有，则新增一条“无实例数据”
            int nodesNum = 0;
            for (NodeParam m : nodesLastInfo) {
                if ((qparam.getModelId()).equals(m.getCombo())) {
                    nodesNum++;
                }
            }
            if (nodesNum == 0) {
                NodeParam emptyNode = new NodeParam();
                emptyNode.initEmptyNode(qparam.getModelId());
                nodesInfo.add(emptyNode);
            }

            //实例删除后，判断该模型下是否还有实例，没有，则新增一条“无实例”的连接线
            //该“无实例”需要连接上级模型和下级模型
            if (nodesNum == 0) {
                for (String source : sourceList) {
                    NodeParam src = new NodeParam();
                    src.setId(source);
                    NodeParam dest = new NodeParam();
                    dest.initEmptyNode(qparam.getModelId());

                    EdgeParam edgeParam = new EdgeParam(src, dest);
                    edgesInfo.add(edgeParam);
                }

                for (String target : targetList) {
                    NodeParam src = new NodeParam();
                    src.initEmptyNode(qparam.getModelId());
                    NodeParam dest = new NodeParam();
                    dest.setId(target);

                    EdgeParam edgeParam = new EdgeParam(src, dest);
                    edgesInfo.add(edgeParam);
                }
            }
        }
    }

    private LastData doAddNewModel(QueryInstanceRelationToPoParam param) {
        LastData lastData = param.getData();
        List<NodeParam> nodeParams = lastData.getNodes();
        List<ComboParam> comboParams = lastData.getCombos();

        //需要新增一个无实例数据
        NodeParam nodeParam = new NodeParam();
        nodeParam.initEmptyNode(param.getOppoRelationsParamList().get(0).getModelId());

        //找到节点插入位置
        QueryInstanceRelationsParam own = param.getOwmRelationsParam();
        NodeParam start = new NodeParam(own.getModelId(), own.getInstanceIds().get(0));
        NodePosInfo pos = findAddModelPos(start, lastData);
        if (0 == pos.getPos()) {
            nodeParams.add(nodeParam);
        } else {
            nodeParams.add(pos.getPos(), nodeParam);
        }
        nodeParam.setLevel(pos.getLevel() + 1);

        QueryInstanceRelationsParam qparam = param.getOppoRelationsParamList().get(0);
        ComboParam comboParam = new ComboParam(qparam.getModelId(), qparam.getModelName(), 0);
        if (0 == pos.getComboPos()) {
            comboParams.add(comboParam);
        } else {
            comboParams.add(pos.getComboPos(), comboParam);
        }
        return lastData;
    }

    //新增模型的实例节点放在下一个级别的后面
    private NodePosInfo findAddModelPos(NodeParam nodeParam, LastData data) {
        NodePosInfo nodePosInfo = new NodePosInfo();
        if (null != data.getNodes()) {
            int level = 0;
            int nextLevel = 99;
            boolean find = false;

            NodeParam node = null;
            for (int i = 0; i < data.getNodes().size(); i++) {
                NodeParam cnode = data.getNodes().get(i);
                //确定新增节点的层级的前一级
                if (nodeParam.equals(cnode)) {
                    level = cnode.getLevel();
                    nextLevel = level + 1;
                    find = true;
                }

                if (find && cnode.getLevel() > nextLevel) {
                    nodePosInfo.setPos(i);
                    node = cnode;
                    break;
                }
            }

            if (null != node) {
                ComboParam combo = new ComboParam(node.getCombo(), node.getLabel(), 0);
                for (int i = 0; i < data.getCombos().size(); i++) {
                    ComboParam comboParam = data.getCombos().get(i);
                    if (combo.equals(comboParam)) {
                        nodePosInfo.setComboPos(i);
                    }
                }
            }

            nodePosInfo.setLevel(level);
        }
        return nodePosInfo;
    }

    //查询实例拓扑数据,并按照左到右,上到下的顺序,对点,边,组对应排序
    private void initInstanceTopo(QueryInstanceRelationToPoParam param, InstanceTopoView instanceTopoView) throws Exception {
        LastData data = new LastData();
        List<String> instanceList = new ArrayList<>();
        String instanceId = param.getOwmRelationsParam().getInstanceIds().get(0);
        instanceList.add(instanceId);
        List<EdgeParam> edgeParamList = new ArrayList<>();
        data.setEdges(edgeParamList);
        if (!StringUtils.equals(param.getInstanceViewId(), InstanceTopoCommonView.DEFAULT_INSTANCE_VIEW_ID)) {
            // 自定义视图
            String key = String.format("%s_%s_%s", param.getOwmRelationsParam().getModelId(), instanceId, param.getInstanceViewId());
            Optional<InstanceTopoCustomView> result = instanceTopoCustomViewMapper.findById(key);
            InstanceTopoCustomView instanceTopoCommonView = null;
            if (result.isPresent()) {
                instanceTopoCommonView = result.get();
                analysisCustomInstanceToPo(instanceTopoCommonView, instanceList, edgeParamList, param.getInstanceViewId());
            }
        } else {
            // 默认视图
            String key = String.format("%s_%s", param.getOwmRelationsParam().getModelId(), instanceId);
            Optional<InstanceTopoCommonView> result = instanceTopoCommonViewMapper.findById(key);
            InstanceTopoCommonView instanceTopoCommonView = null;
            if (result.isPresent()) {
                instanceTopoCommonView = result.get();
                analysisCommonInstanceToPo(instanceTopoCommonView, instanceList, edgeParamList);
            }
        }

        //查询所有关系信息,根据模型id获取每个关系对应的名称
        ModelAsset modelAsset = null;
        Optional<ModelAsset> result = modelAssetMapper.findById(param.getOwmRelationsParam().getModelId());
        Map<String, ModelAsset> id2ModelAssetMap = new HashMap<>();
        if (result.isPresent()) {
            modelAsset = result.get();
        }
        analysisModelRelation(modelAsset, id2ModelAssetMap, null, null, 0);

        // 查询当前实例视图模型告警权重配置
        List<ModelAlertWeightInfo> modelAlertWeightInfoList = modelAlertWeightInfoMapper.find(new Query(
                CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getInstanceId)).is(instanceId)
                        .andOperator(CriteriaWrapper.where(CMDBTool.getFieldName(ModelAlertWeightInfo::getInstanceViewId)).is(param.getInstanceViewId()))));
        Map<String, Integer> modelId2WeightMap = modelAlertWeightInfoList.stream().collect(Collectors.toMap(ModelAlertWeightInfo::getOwnModelId, ModelAlertWeightInfo::getWeight, (o1, o2) -> o2));

        InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
        Map<String, InstanceInfo> id2InstanceInfoMap = instanceService.selectListByIds(instanceList).stream().collect(Collectors.toMap(InstanceInfo::getId, item -> item));
        List<String> modelIds = id2InstanceInfoMap.values().stream().map(InstanceInfo::getModelId).distinct().toList();
        InstanceInfoExtend instanceInfoExtend = instanceService.selectAggregateById(instanceId);

        // 添加当前模型跟实例节点
        ComboParam currentCombo = new ComboParam();
        currentCombo.setId(instanceInfoExtend.getModelId());
        currentCombo.setLabel(instanceInfoExtend.getModelName());
        data.addComboParam(currentCombo);

        NodeParam currentNode = new NodeParam();
        currentNode.setCombo(param.getOwmRelationsParam().getModelId());
        currentNode.setLabel(id2InstanceInfoMap.get(instanceId).getInstanceName());
        currentNode.setLevel(0);
        currentNode.setRealId(id2InstanceInfoMap.get(instanceId).getId());
        currentNode.setId(String.format("%s_%s", currentNode.getCombo(), currentNode.getRealId()));
        data.addNodeParam(currentNode);

        // 添加combo节点
        for (Map.Entry<String, ModelAsset> entry : id2ModelAssetMap.entrySet()) {
            if (!StringUtils.equals(param.getOwmRelationsParam().getModelId(), entry.getKey()) && modelIds.contains(entry.getKey())) {
                data.addComboParam(new ComboParam(entry.getKey(), entry.getValue().getModelRelationInfo() == null ? "未知" : entry.getValue().getModelRelationInfo().getRelationName(), modelId2WeightMap.getOrDefault(entry.getKey(), 0)));
            }
        }

        InstanceInfo instanceInfo;
        for (Map.Entry<String, InstanceInfo> entry : id2InstanceInfoMap.entrySet()) {
            instanceInfo = entry.getValue();
            if (!StringUtils.equals(instanceId, entry.getKey()) && id2ModelAssetMap.containsKey(instanceInfo.getModelId())) {
                NodeParam instanceNode = new NodeParam();
                instanceNode.setCombo(instanceInfo.getModelId());
                instanceNode.setLabel(instanceInfo.getInstanceName());
                instanceNode.setLevel(id2ModelAssetMap.get(instanceInfo.getModelId()).getLevel());
                instanceNode.setRealId(instanceInfo.getId());
                instanceNode.setId(String.format("%s_%s", instanceNode.getCombo(), instanceNode.getRealId()));
                data.addNodeParam(instanceNode);
            }
        }

        instanceTopoView.setData(data);
    }

    private void analysisModelRelation(ModelAsset modelAsset, Map<String, ModelAsset> id2ModelAssetMap, String currentModelId, ModelRelationDTO modelRelationDTO, int level) throws Exception {
        if (modelAsset != null) {
            if (modelRelationDTO != null && modelRelationDTO.getRelationInfoMap() != null) {
                for (Object mapData : modelRelationDTO.getRelationInfoMap().values()) {
                    ModelRelationInfo modelRelationInfo = ListMapObjUtils.mapToBean((Map) mapData, ModelRelationInfo.class);
                    if (!StringUtils.equals(modelRelationInfo.getModelId(), currentModelId)) {
                        modelAsset.setModelRelationInfo(modelRelationInfo);
                        break;
                    }
                }
            }
            modelAsset.setLevel(level);
            id2ModelAssetMap.put(modelAsset.getId(), modelAsset);
            if (level >= 0) {
                for (ModelRelate modelRelate : modelAsset.getOutModelRelates()) {
                    if (modelRelate.getEndNode() != null) {
                        analysisModelRelation(modelRelate.getEndNode(), id2ModelAssetMap, modelRelate.getEndNode().getId(), modelRelate.getModelRelationDTO(), ++level);
                    }
                }
            }
            if (level <= 0) {
                for (ModelRelate modelRelate : modelAsset.getInModelRelates()) {
                    if (modelRelate.getEndNode() != null) {
                        analysisModelRelation(modelRelate.getEndNode(), id2ModelAssetMap, modelRelate.getEndNode().getId(), modelRelate.getModelRelationDTO(), --level);
                    }
                }
            }
        }
    }

    private void analysisCustomInstanceToPo(InstanceTopoCustomView instanceTopoCustomView, List<String> instanceId, List<EdgeParam> edgeParamList, String instanceViewId) {
        if (instanceTopoCustomView != null) {
            instanceId.add(instanceTopoCustomView.getInstanceId());
            if (instanceTopoCustomView.getOutInstanceRelations() != null) {
                EdgeParam edgeParam;
                // 创建关系
                for (InstanceCustomRelation instanceCustomRelation : instanceTopoCustomView.getOutInstanceRelations()) {
                    edgeParam = new EdgeParam(instanceTopoCustomView.getId().replace("_" + instanceViewId, ""), instanceCustomRelation.getEndNode().getId().replace("_" + instanceViewId, ""));
                    edgeParamList.add(edgeParam);
                    analysisCustomInstanceToPo(instanceCustomRelation.getEndNode(), instanceId, edgeParamList, instanceViewId);
                }
            }
        }
    }

    private void analysisCommonInstanceToPo(InstanceTopoCommonView InstanceTopoCommonView, List<String> instanceId, List<EdgeParam> edgeParamList) {
        if (InstanceTopoCommonView != null) {
            instanceId.add(InstanceTopoCommonView.getInstanceId());
            if (InstanceTopoCommonView.getOutInstanceRelations() != null) {
                EdgeParam edgeParam;
                // 创建下一级关系
                for (InstanceCommonRelation instanceCommonRelation : InstanceTopoCommonView.getOutInstanceRelations()) {
                    edgeParam = new EdgeParam(InstanceTopoCommonView.getId(), instanceCommonRelation.getEndNode().getId());
                    edgeParamList.add(edgeParam);
                    analysisCommonInstanceToPo(instanceCommonRelation.getEndNode(), instanceId, edgeParamList);
                }
            }
            if (InstanceTopoCommonView.getInInstanceRelations() != null) {
                EdgeParam edgeParam;
                // 创建上一级关系
                for (InstanceCommonRelation instanceCommonRelation : InstanceTopoCommonView.getInInstanceRelations()) {
                    edgeParam = new EdgeParam(InstanceTopoCommonView.getId(), instanceCommonRelation.getEndNode().getId());
                    edgeParamList.add(edgeParam);
                    analysisCommonInstanceToPo(instanceCommonRelation.getEndNode(), instanceId, edgeParamList);
                }
            }
        }
    }

    private void addEdgeParams(Session session, List<EdgeParam> edgeParams, Map<String, List<EdgeParam>> edgeMap, NodeParam start, String space
            , int level, Set<ModelConn> modelConnSet, List<String> allInstanceIds) {
        List<EdgeParam> findEdgeParams = ModelAssetUtils.findEdgeBySpace(session, start, space, level);
        for (EdgeParam edgeParam : findEdgeParams) {
            ModelConn modelConn = new ModelConn(edgeParam);
            if (!modelConnSet.contains(modelConn)) {
                continue;
            }
            if (!edgeParams.contains(edgeParam)) {
                edgeParams.add(edgeParam);
                doAddNodeParam(new NodeParam(edgeParam.getSource()), allInstanceIds);
                doAddNodeParam(new NodeParam(edgeParam.getTarget()), allInstanceIds);

                List<EdgeParam> list = edgeMap.get(edgeParam.getSource());
                if (null == list) {
                    list = new ArrayList<>();
                    edgeMap.put(edgeParam.getSource(), list);
                }
                list.add(edgeParam);
            }
        }
    }

    private void doAddNodeParam(NodeParam nodeParam, List<String> allInstanceIds) {
        if (!allInstanceIds.contains(nodeParam.getRealId())) {
            allInstanceIds.add(nodeParam.getRealId());
        }
    }

    private void doVisitModelAsset(ModelAsset modelAsset, Map<String, ModelRelationDTO> modelAssetMap
            , Set<Long> visitedRelation, Set<ModelConn> modelConnSet) {
        if (null == modelAsset.getOutModelRelates()) {
            return;
        }

        for (ModelRelate modelRelate : modelAsset.getOutModelRelates()) {
            if (visitedRelation.contains(modelRelate.getRelationId())) {
                continue;
            }
            ModelConn modelConn = new ModelConn(modelAsset.getId(), modelRelate.getEndNode().getId());
            modelConnSet.add(modelConn);
            visitedRelation.add(modelRelate.getRelationId());
            addModelRelationDTO(modelAsset, modelRelate, modelAssetMap);
            addModelRelationDTO(modelRelate.getEndNode(), modelRelate, modelAssetMap);
            doVisitModelAsset(modelRelate.getEndNode(), modelAssetMap, visitedRelation, modelConnSet);
        }
    }

    private void addModelRelationDTO(ModelAsset modelAsset, ModelRelate modelRelate, Map<String, ModelRelationDTO> modelAssetMap) {
        ModelRelationDTO modelRelationDTO = modelAssetMap.get(modelAsset.getId());
        if (null == modelRelationDTO) {
            modelRelationDTO = modelRelate.getModelRelationDTO();
            modelAssetMap.put(modelAsset.getId(), modelRelationDTO);
        }
    }
}
